Stock analysis with R
Selecting suitable stocks to build a good portfolio
1 Asset prices
1.1 Daily prices
## Rows: 3,820
## Columns: 8
## $ symbol <chr> "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "~
## $ date <date> 2018-01-02, 2018-01-03, 2018-01-04, 2018-01-05, 2018-01-08, ~
## $ open <dbl> 177.68, 181.88, 184.90, 185.59, 187.20, 188.70, 186.94, 188.4~
## $ high <dbl> 181.58, 184.78, 186.21, 186.90, 188.90, 188.80, 187.89, 188.4~
## $ low <dbl> 177.55, 181.33, 184.10, 184.93, 186.33, 187.10, 185.63, 187.3~
## $ close <dbl> 181.42, 184.67, 184.33, 186.85, 188.28, 187.87, 187.84, 187.7~
## $ volume <dbl> 18151900, 16886600, 13880900, 13574500, 17994700, 12393100, 1~
## $ adjusted <dbl> 181.42, 184.67, 184.33, 186.85, 188.28, 187.87, 187.84, 187.7~
1.2 Monthly stock prices
## Rows: 184
## Columns: 8
## Groups: symbol [4]
## $ symbol <chr> "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "~
## $ date <date> 2018-01-31, 2018-02-28, 2018-03-29, 2018-04-30, 2018-05-31, ~
## $ open <dbl> 188.37, 182.30, 155.15, 173.79, 187.87, 197.32, 170.67, 177.1~
## $ high <dbl> 189.83, 182.88, 161.42, 175.72, 192.72, 197.60, 174.24, 177.6~
## $ low <dbl> 185.22, 178.14, 154.14, 171.71, 187.48, 193.96, 170.00, 174.9~
## $ close <dbl> 186.89, 178.32, 159.79, 172.00, 191.78, 194.32, 172.58, 175.7~
## $ volume <dbl> 43275100, 18783000, 59434300, 20750500, 30782600, 15811600, 4~
## $ adjusted <dbl> 186.89, 178.32, 159.79, 172.00, 191.78, 194.32, 172.58, 175.7~
1.3 Yearly stock prices
## Rows: 16
## Columns: 8
## Groups: symbol [4]
## $ symbol <chr> "FB", "FB", "FB", "FB", "AMZN", "AMZN", "AMZN", "AMZN", "AAPL~
## $ date <date> 2018-12-31, 2019-12-31, 2020-12-31, 2021-10-15, 2018-12-31, ~
## $ open <dbl> 134.4500, 204.0000, 272.0000, 328.6800, 1510.8000, 1842.0000,~
## $ high <dbl> 134.64, 205.56, 277.09, 329.07, 1520.76, 1853.26, 3282.92, 34~
## $ low <dbl> 129.950, 203.600, 269.810, 322.510, 1487.000, 1832.230, 3241.~
## $ close <dbl> 131.0900, 205.2500, 273.1600, 324.7600, 1501.9700, 1847.8400,~
## $ volume <dbl> 24625300, 8953500, 12900400, 21575100, 6954500, 2506500, 2957~
## $ adjusted <dbl> 131.09000, 205.25000, 273.16000, 324.76001, 1501.96997, 1847.~
# Asset prices to returns
1.4 Daily return
1.5 Monthly returns
1.6 Yearly returns
2 Mean return for the whole period
2.1 Daily mean return for the whole period
## # A tibble: 4 x 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 0.13 0.15 11.3 -13.8
## 2 AMZN 0.11 0.16 9.03 -8.25
## 3 FB 0.06 0.12 10.3 -21.0
## 4 GOOG 0.1 0.19 9.94 -11.8
2.2 Monthly mean return for the whole period
## # A tibble: 4 x 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 2.73 4.82 19.6 -20.0
## 2 AMZN 2.29 3.1 23.8 -22.6
## 3 FB 1.27 1 24.0 -14.3
## 4 GOOG 2.13 2.68 15.3 -14.1
2.3 Yearly mean return for the whole period
## # A tibble: 4 x 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 31.4 34.6 63.6 -7.32
## 2 AMZN 26.3 22.0 56.7 4.56
## 3 FB 14.6 22.9 44.8 -32.5
## 4 GOOG 24.5 26.3 48.1 -2.8
3 Stock volatility for the whole period
3.1 Daily Stock volatility for the whole period
## # A tibble: 4 x 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 0.13 0.15 2.1 11.3 -13.8
## 2 AMZN 0.11 0.16 1.98 9.03 -8.25
## 3 FB 0.06 0.12 2.3 10.3 -21.0
## 4 GOOG 0.1 0.19 1.86 9.94 -11.8
3.2 Monthly Stock volatility for the whole period
## # A tibble: 4 x 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 2.73 4.82 9.05 19.6 -20.0
## 2 AMZN 2.29 3.1 8.4 23.8 -22.6
## 3 FB 1.27 1 8.76 24.0 -14.3
## 4 GOOG 2.13 2.68 6.83 15.3 -14.1
3.3 Yearly Stock volatility for the whole period
## # A tibble: 4 x 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 31.4 34.6 35.8 63.6 -7.32
## 2 AMZN 26.3 22.0 21.9 56.7 4.56
## 3 FB 14.6 22.9 33.3 44.8 -32.5
## 4 GOOG 24.5 26.3 20.9 48.1 -2.8
4 Rolling stock volatility
We have calculated the average volatility for the entire life of the portfolio but it would help if we could better understand how that volatility has changed over time or behaved in different market conditions.
4.1 Rolling daily stock volatility
4.1.1 Rolling daily mean return
4.1.2 Rolling maximum daily return
4.1.3 Rolling minimum daily return
4.1.4 Rolling daily volatility return
4.2 Rolling monthly stock volatility
## Rows: 184
## Columns: 8
## Groups: symbol [4]
## $ symbol <chr> "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", ~
## $ date <date> 2018-01-31, 2018-02-28, 2018-03-29, 2018-04-30,~
## $ monthly.returns <dbl> 0.029705429, -0.046940475, -0.109719319, 0.07363~
## $ rolling_mean_return <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -0.0~
## $ rolling_median_return <dbl> NA, NA, NA, NA, NA, -0.056610878, -0.056610878, ~
## $ rolling_max_return <dbl> NA, NA, NA, NA, NA, 0.1088544, 0.2402517, 0.2402~
## $ rolling_min_return <dbl> NA, NA, NA, NA, NA, -0.11864541, -0.11864541, -0~
## $ rolling_volatility <dbl> NA, NA, NA, NA, NA, 0.07370874, 0.10630541, 0.10~
4.2.1 Rolling monthly mean return
4.2.2 Rolling maximum monthly return
4.2.3 Rolling minimum monthly return
4.2.4 Rolling monthly volatility return
5 Shape of return distribution
The shape of the return distribution of a stock contains many important information of the riskiness of the stock investment.
If the stock return density distribution is a belled-shape of a normal distribution then gains are equally likely as losses of the same magnitude. For many financial assets, however, their distribution tends to be skewed to the left with tails that are fatter than those of a normal distribution. As a consequence, when we zoom in on the left tail of the histogram of financial returns, we often find that there are more extreme negative returns happening than is possible under a normal distribution.
Typically, investors also report the skewness and kurtosis of their portfolio returns to indicate two types of non-normality in their return distribution, namely assymmetry and fat tails. The skewness is designed such that it is approximately zero when the distribution is symmetric. When the skewness is negative, it indicates that large negative returns occur more often than large positive returns. A negative skewness thus corresponds to a distribution with a long left tail. The opposite is true in case of a positive skewness. Large positive returns are more likely than large negative returns, and the distribution has a long tail to the right.
A distribution with fat tails is a distribution in which extremely large positive or negative returns occur more often than a normal distribution would predict. A useful statistic to detect fat tails is the kurtosis. Its value is 3 for normal distribution. The larger the excess kurtosis, the fatter the tails are compared to the tails of a normal distribution.
5.1 Skewness and kurtosis for the whole period
5.1.1 Daily returns
## # A tibble: 4 x 3
## # Groups: symbol [4]
## symbol Skewness Kurtosis
## <chr> <dbl> <dbl>
## 1 FB -0.988 14.1
## 2 AMZN -0.151 5.63
## 3 AAPL -0.354 8.96
## 4 GOOG -0.285 8.29
5.1.2 Monthly returns
## # A tibble: 4 x 3
## # Groups: symbol [4]
## symbol Skewness Kurtosis
## <chr> <dbl> <dbl>
## 1 FB 0.432 2.80
## 2 AMZN -0.0908 3.93
## 3 AAPL -0.386 2.56
## 4 GOOG -0.334 2.61
5.2 Rolling monthly Skewness and Kurtosis
6 Downside risk measures
The standard deviation gives equal weight to positive and negative returns in calculating the return variability. When the return distribution is asymmetric (skewed), investors use additional risk measures that focus on describing the potential losses. One such measure of downside risk is the Semi-Deviation. The Semi-Deviation is the calculation of the variability of returns below the mean returr, with the following formula:
\[\sigma= \sqrt{\dfrac{(R_1-\bar R)^2+...+(R_n-\bar R)^2}{n}}\] where \(R_i<\bar R\).
Another more popular measure is the so-called Value-at-Risk (or VaR). Loosely speaking, the VaR corresponds to the \(5\%\) quantile of the return distribution, meaning that a more negative return can only happen with a probability of 5%. For example you might ask: “what is the largest loss I could potentially take within the next quarter such that I only have \(5\%\) probability of observing an even larger loss?”
The expected shortfall is another measure of risk that focuses on the average loss below the \(5\%\) VaR quantile.
The volatility, semi-deviation, value-at-risk, and expected shortfall are all measures that describe risk over one period. These metrics do not do a great job at describing the worst-case risk of buying at a peak and selling at a trough. This sort of risk can be quantified by analyzing the portfolio’s drawdowns, or peak-to-trough decline in cumulative returns.
## # A tibble: 4 x 5
## # Groups: symbol [4]
## symbol SemiDeviation `HistoricalVaR(95%)` `HistoricalES(95%)` MaximumDrawdown
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 FB 0.0171 -0.0345 -0.055 0.457
## 2 AMZN 0.0143 -0.0314 -0.0471 0.365
## 3 AAPL 0.0153 -0.0317 -0.0499 0.402
## 4 GOOG 0.0136 -0.0295 -0.0458 0.327
## From Trough To Depth Length To Trough Recovery
## 1 2018-07-26 2018-12-24 2020-08-06 -0.4574 512 105 407
## 2 2018-02-02 2018-03-27 2018-06-18 -0.2206 94 37 57
## 3 2020-08-27 2021-01-14 2021-04-29 -0.2126 169 97 72
## 4 2021-09-08 2021-10-12 <NA> -0.1565 29 25 NA
## 5 2021-04-30 2021-05-12 2021-05-27 -0.0831 20 9 11
7 Applications on Vietnamese stocks
7.1 Scraping stock prices from websites
7.2 Daily prices
7.3 Monthly stock prices
## Rows: 294
## Columns: 13
## Groups: symbol [6]
## $ symbol <chr> "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC~
## $ date <date> 2017-10-31, 2017-11-30, 2017-12-29, 2018-01-3~
## $ Last_closed_price <dbl> 42.61, 55.98, 56.86, 62.44, 68.69, 84.48, 93.3~
## $ absolute_price_change <dbl> 0.37, -1.25, -0.07, 0.73, 1.03, 1.62, -0.73, 3~
## $ Percentage_price_change <dbl> 0.0086834077, -0.0223294034, -0.0012310939, 0.~
## $ Closed_price <dbl> 42.98, 54.73, 56.79, 63.18, 69.72, 86.10, 92.5~
## $ Trading_Volume <dbl> 1225710, 1728020, 2105550, 5163910, 1652330, 1~
## $ Open_price <dbl> 42.83, 55.98, 57.01, 62.81, 67.81, 84.55, 90.1~
## $ Highest_price <dbl> 43.20, 56.35, 58.70, 64.94, 69.86, 86.10, 92.9~
## $ Lowest_price <dbl> 42.39, 54.73, 56.57, 62.52, 67.81, 83.75, 89.6~
## $ Exchange_volume <dbl> 0, 0, 0, 0, 20000, 0, 0, 0, 0, 0, 0, 3574116, ~
## $ Foregin_buy_volume <dbl> 386500, 57190, 423670, 1636030, 792710, 572890~
## $ Foreign_sell_volume <dbl> 248700, 587400, 327100, 1731360, 529000, 43260~
7.4 Yearly stock prices
## Rows: 30
## Columns: 13
## Groups: symbol [6]
## $ symbol <chr> "VIC", "VIC", "VIC", "VIC", "VIC", "HAG", "HAG~
## $ date <date> 2017-12-29, 2018-12-28, 2019-12-31, 2020-12-3~
## $ Last_closed_price <dbl> 56.86, 91.02, 102.22, 96.44, 92.50, 7.45, 4.94~
## $ absolute_price_change <dbl> -0.07, -6.31, 0.00, -0.27, 0.10, -0.10, -0.06,~
## $ Percentage_price_change <dbl> -0.001231094, -0.069325423, 0.000000000, -0.00~
## $ Closed_price <dbl> 56.79, 84.71, 102.22, 96.18, 92.60, 7.35, 4.88~
## $ Trading_Volume <dbl> 2105550, 381320, 614630, 656040, 1553700, 2334~
## $ Open_price <dbl> 57.01, 91.82, 102.22, 96.44, 92.50, 7.45, 4.93~
## $ Highest_price <dbl> 58.70, 91.91, 102.22, 97.16, 93.00, 7.46, 4.97~
## $ Lowest_price <dbl> 56.57, 84.71, 101.42, 93.78, 92.00, 7.33, 4.87~
## $ Exchange_volume <dbl> 0, 0, 0, 0, 0, 2728000, 240000, 0, 0, 0, 37474~
## $ Foregin_buy_volume <dbl> 423670, 60730, 108140, 134710, 72300, 7140, 0,~
## $ Foreign_sell_volume <dbl> 327100, 13930, 445890, 165460, 102000, 1000, 0~
# Asset prices to returns
7.5 Daily return
7.6 Monthly returns
## Yearly returns
7.7 Daily mean return for the whole period
## # A tibble: 6 x 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 ^VN30 0.06 0.16 7.81 -6.96
## 2 ^VNINDEX 0.05 0.15 4.86 -6.91
## 3 E1VFVN30 0.06 0.0700 7.43 -7.23
## 4 HAG -0.05 0 6.77 -7.25
## 5 VIC 0.08 0 6.76 -7.26
## 6 VNM 0 0 6.74 -7.25
7.8 Monthly mean return for the whole period
## # A tibble: 4 x 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 2.73 4.82 19.6 -20.0
## 2 AMZN 2.29 3.1 23.8 -22.6
## 3 FB 1.27 1 24.0 -14.3
## 4 GOOG 2.13 2.68 15.3 -14.1
7.9 Yearly mean return for the whole period
## # A tibble: 6 x 5
## symbol mean_return median_return maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 ^VN30 12.3 18.4 34.0 -13.2
## 2 ^VNINDEX 10.6 13.9 23.2 -9.78
## 3 E1VFVN30 12.1 18.7 31.1 -12.3
## 4 HAG -9.81 -12.5 27.7 -41.0
## 5 VIC 16.7 18.8 40.0 -6.09
## 6 VNM 0.08 0.72 34.6 -34.1
7.10 Daily Stock volatility for the whole period
## # A tibble: 6 x 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 ^VN30 0.06 0.16 1.37 7.81 -6.96
## 2 ^VNINDEX 0.05 0.15 1.26 4.86 -6.91
## 3 E1VFVN30 0.06 0.0700 1.52 7.43 -7.23
## 4 HAG -0.05 0 2.61 6.77 -7.25
## 5 VIC 0.08 0 1.91 6.76 -7.26
## 6 VNM 0 0 1.64 6.74 -7.25
7.11 Monthly Stock volatility for the whole period
## # A tibble: 4 x 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 AAPL 2.73 4.82 9.05 19.6 -20.0
## 2 AMZN 2.29 3.1 8.4 23.8 -22.6
## 3 FB 1.27 1 8.76 24.0 -14.3
## 4 GOOG 2.13 2.68 6.83 15.3 -14.1
7.12 Yearly Stock volatility for the whole period
## # A tibble: 6 x 6
## symbol mean_return median_return volatility maximum_return minimum_return
## <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 ^VN30 12.3 18.4 18.1 34.0 -13.2
## 2 ^VNINDEX 10.6 13.9 12.8 23.2 -9.78
## 3 E1VFVN30 12.1 18.7 16.9 31.1 -12.3
## 4 HAG -9.81 -12.5 25.2 27.7 -41.0
## 5 VIC 16.7 18.8 21.3 40.0 -6.09
## 6 VNM 0.08 0.72 26.4 34.6 -34.1
7.13 Rolling daily stock volatility
7.13.1 Rolling daily mean return
7.13.2 Rolling maximum daily return
7.13.3 Rolling minimum daily return
7.13.4 Rolling daily volatility return
7.14 Rolling monthly stock volatility
7.14.1 Rolling monthly mean return
7.14.2 Rolling maximum monthly return
7.14.3 Rolling minimum monthly return
7.14.4 Rolling monthly volatility return
7.15 Skewness and kurtosis for the whole period
7.15.1 Daily returns
## # A tibble: 6 x 3
## # Groups: symbol [6]
## symbol Skewness Kurtosis
## <chr> <dbl> <dbl>
## 1 VIC -0.0592 6.95
## 2 HAG 0.136 4.26
## 3 VNM 0.0384 6.35
## 4 E1VFVN30 -0.399 7.30
## 5 ^VN30 -0.857 7.97
## 6 ^VNINDEX -1.14 7.75
7.15.2 Monthly returns
## # A tibble: 4 x 3
## # Groups: symbol [4]
## symbol Skewness Kurtosis
## <chr> <dbl> <dbl>
## 1 FB 0.432 2.80
## 2 AMZN -0.0908 3.93
## 3 AAPL -0.386 2.56
## 4 GOOG -0.334 2.61
7.16 Rolling monthly Skewness and Kurtosis
7.17 Downside risk measures
## # A tibble: 6 x 5
## # Groups: symbol [6]
## symbol SemiDeviation `HistoricalVaR(95%)` `HistoricalES(95%~ MaximumDrawdown
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 VIC 0.0134 -0.0276 -0.0471 0.443
## 2 HAG 0.0179 -0.0423 -0.062 0.748
## 3 VNM 0.0115 -0.0253 -0.0374 0.534
## 4 E1VFVN30 0.0112 -0.0228 -0.0399 0.504
## 5 ^VN30 0.0106 -0.0239 -0.0382 0.501
## 6 ^VNINDEX 0.0099 -0.0226 -0.0358 0.470
## Rows: 955
## Columns: 8
## $ symbol <chr> "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "FB", "~
## $ date <date> 2018-01-02, 2018-01-03, 2018-01-04, 2018-01-05, 2018-01-08, ~
## $ open <dbl> 177.68, 181.88, 184.90, 185.59, 187.20, 188.70, 186.94, 188.4~
## $ high <dbl> 181.58, 184.78, 186.21, 186.90, 188.90, 188.80, 187.89, 188.4~
## $ low <dbl> 177.55, 181.33, 184.10, 184.93, 186.33, 187.10, 185.63, 187.3~
## $ close <dbl> 181.42, 184.67, 184.33, 186.85, 188.28, 187.87, 187.84, 187.7~
## $ volume <dbl> 18151900, 16886600, 13880900, 13574500, 17994700, 12393100, 1~
## $ adjusted <dbl> 181.42, 184.67, 184.33, 186.85, 188.28, 187.87, 187.84, 187.7~
7.18 VIC stock performance
## Rows: 1,000
## Columns: 7
## $ symbol <chr> "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", ~
## $ date <date> 2021-10-15, 2021-10-14, 2021-10-13, 2021-10-12, 2021-10-11, 20~
## $ open <dbl> 92.5, 93.2, 93.0, 92.0, 89.4, 89.0, 88.3, 88.8, 87.8, 87.6, 88.~
## $ high <dbl> 93.0, 93.2, 93.8, 93.0, 92.0, 89.5, 89.5, 89.0, 88.8, 88.0, 88.~
## $ low <dbl> 92.0, 91.5, 92.8, 92.0, 89.4, 88.8, 88.3, 88.1, 87.1, 87.1, 87.~
## $ close <dbl> 92.6, 92.5, 93.1, 92.9, 91.9, 89.3, 88.8, 88.6, 88.6, 87.8, 87.~
## $ volume <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 22499, 0, 2443045, 0, 100067, 40077, 16~
## From Trough To Depth Length To Trough Recovery
## 1 2019-08-23 2020-03-24 2021-04-13 -0.4431 411 146 265
## 2 2021-04-20 2021-09-21 <NA> -0.3431 125 106 NA
## 3 2018-04-10 2018-05-23 2019-02-21 -0.2480 217 29 188
## 4 2018-01-16 2018-02-09 2018-02-21 -0.1065 20 17 3
## 5 2019-03-19 2019-04-18 2019-07-24 -0.1036 88 22 66
7.19 HAG stock performance
## Rows: 1,000
## Columns: 7
## $ symbol <chr> "HAG", "HAG", "HAG", "HAG", "HAG", "HAG", "HAG", "HAG", "HAG", ~
## $ date <date> 2021-10-15, 2021-10-14, 2021-10-13, 2021-10-12, 2021-10-11, 20~
## $ open <dbl> 5.20, 5.03, 5.01, 5.04, 5.12, 5.05, 5.04, 5.00, 5.03, 5.01, 5.0~
## $ high <dbl> 5.24, 5.28, 5.07, 5.08, 5.13, 5.20, 5.08, 5.10, 5.04, 5.06, 5.0~
## $ low <dbl> 5.08, 5.03, 5.01, 5.00, 5.04, 5.04, 5.03, 5.00, 4.99, 4.98, 5.0~
## $ close <dbl> 5.10, 5.20, 5.04, 5.02, 5.04, 5.09, 5.04, 5.03, 5.01, 5.00, 5.0~
## $ volume <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3856235, 0, 0, 0, 2000000, 400000~
## From Trough To Depth Length To Trough Recovery
## 1 2017-10-17 2020-03-30 <NA> -0.7481 1000 610 NA